# Purl::Commands
#
# Module that handles the system commands. Pre-coded commands registered
#   with the system.
package Purl::Commands;
$VERSION = 0.01;
use strict;

use Purl::Commands::CO;

{

    
    # A closure to implement a class attribute and
    # private methods.

    my %_list;

    sub _get_list {
        my $return  = "";
        my $command = "";
        foreach $command ( keys %_list ) {
            $return .= $command . " ";
        }
        return $return;
    }

    sub _get_count {
        my $return = 0;
        $return = keys %_list;
        return $return;
    }

    # verify: Return true if command is registered.
    sub _verify { my $command = shift; return 1 if $_list{$command}; }

    sub _set_registered_command {
        my ( $command, $argRef ) = @_;

        if ( ref($argRef) eq 'HASH' ) {

            #           print "DEBUG: Loading $$argRef{name} - $command\n";

            # This is a new item. Make a new object.
            my $co = Purl::Commands::CO->new(%$argRef);
            $_list{$command} = $co;
            return $co;
        }
        else {

            # This is an alias with an object reference,
            # just add it to the list.
            #      print "SRC: $command, $args{name}, $args{subRef}\n";
            $_list{$command} = $argRef;

        }
    }

    sub _get_registered_command {
        my ($command) = @_;
        my $cmdRef = $_list{$command};

        #	print "GRC: $command,$cmdRef,$$cmdRef{name},$$cmdRef{subRef}\n";
        return $cmdRef;
    }
}

# Public Methods

# When you register a command, a reference is saved so it can be found later.
sub register {
    my %args = @_;
    if ( _verify( $args{name} ) && ( !exists $args{OverloadException} ) ) {

        # Command already registered with this name.
        # Throw a fit.
        #       print "Command $args{name} exists.\n";
    }
    elsif (( length $args{name} < 4 )
        && ( !exists $args{shortCommandException} ) )
    {

        # Command is not long enough.
        # Throw a fit.
        #               print "Command $args{name} is to short.\n";
    }
    else {
        my $co = _set_registered_command( $args{name}, \%args );

        #           print "Registering $args{name}, $args{subRef}\n";
        # For the aliases, just link in the already created object.
        if ( $args{aliases} ) {
            foreach my $alias ( split( / /, $args{aliases} ) ) {
                next
                    if ( ( length $alias < 4 )
                    && ( !exists $args{shortCommandException} ) );
                _set_registered_command( $alias, $co );
            }
        }
    }
}

# Purl::Commands -> run ($actorDBreference, $text)
# Run a command function
#
#
sub run {
    my ( $dbRef, $text ) = @_;

    # Pull the first character, see if it is a command.
    my $command = substr( $text, 0, 1 );
    my $string  = substr( $text, 1 );
    my $switch  = "";

    if (   ( _verify($command) )
        && ( not &Purl::tests::alphaNumeric($command) ) )
    {

        # If the first letter matches a command,
        # and it not a letter or number, get it's info.
        #print "Hey, the letter $first is a command.\n";
        my $cmdRef = _get_registered_command($command);
        $cmdRef->run(
            actor   => $dbRef,
            text    => $string,
            command => $command
        );
        return;
    }

    # Needed, good way to reduce command to one word, taking out switches.
    # For now, it's space only.
    ( $command, $string ) = split( / /,  $text,    2 );
    ( $command, $switch ) = split( /\//, $command, 2 );

    if ( _verify($command) ) {

        # If the first word matches a command, get it's info.
        #       print "Hey, the word $first is a command.\n";
        my $cmdRef = _get_registered_command($command);
        $cmdRef->run(
            actor   => $dbRef,
            text    => $string,
            switch  => $switch,
            command => $command
        );
        return;

        #       print "cmdRef= " . $cmdRef . "\n";
    }

    # If there is no command at this point, send a confused message.
    # -- Or autosay.. eww..
    Purl::comm::sendTextToPlayer(
        target => $dbRef,
        text   => "Huh? Type 'help' for help."
    );

    # print "Error: No command '$text'\n";
    return 0;

}

sub commandList {
    my $return = _get_list;
    return $return;
}

sub commandCount {
    my $return = _get_count;
    return $return;
}

sub loadCommands {

    use Purl::Commands::admin;
    use Purl::Commands::basic;
    use Purl::Commands::building;
    use Purl::Commands::file;
    use Purl::Commands::info;

}

1;

